/*
 *  Copyright (C) 2010 Martin Haulrich <mwh.isv@cbs.dk>
 *
 *  This file is part of the MatrixParser package.
 *
 *  The MatrixParser program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.osdtsystem.incparser.featureextraction;

import org.osdtsystem.incparser.data.CONLLSentence;
import org.osdtsystem.incparser.data.CONLLToken;
import org.osdtsystem.incparser.features.FeatureAggregator;
import org.osdtsystem.incparser.features.FeatureHandler;
import org.osdtsystem.incparser.features.FeatureVector;
import org.osdtsystem.incparser.features.FeatureVectorSparse;
import org.osdtsystem.incparser.graphs.ConllAdapter;
import org.osdtsystem.incparser.graphs.FeatureExtractorOutdateListener;
import org.osdtsystem.incparser.graphs.Graph;
import org.osdtsystem.incparser.graphs.LocalGraph;

/**
 *
 * @author Martin Haulrich
 */
public class MstFeatureExtractorLabelledMartin implements MstFeatureExtractorLabelled {
    FeatureHandler featureHandler;
    ConllAdapter conll;
    int layer = 0;
    int[] layers;

    public MstFeatureExtractorLabelledMartin( ConllAdapter adapter, FeatureHandler featureHandler) {
        this.featureHandler = featureHandler;
        this.conll = adapter;
        this.layer = adapter.layer();
        int[] mylayers = {layer};
        this.layers = mylayers;
    }

    public void extract(FeatureAggregator aggregator, Graph graph, int node) {
        LocalGraph lgraph = graph.localGraph(node, layer);
        int head = lgraph.headNode();
        int type = lgraph.headType();
        extractDependentFeatures(aggregator, graph, node, type, head < node);
        extractHeadFeatures(aggregator, graph, head, type, head < node);
    }

    public void extractDependentFeatures(FeatureAggregator aggregator, Graph graph, int node, int type, boolean headBeforeDep) {
        FeatureVector fvNode = getFeatureVectorLabelled(conll, conll.conllSentence(), type, node, headBeforeDep, true);
        fvNode.addTo(aggregator);
    }

    public void extractHeadFeatures(FeatureAggregator aggregator, Graph graph, int node, int type, boolean headBeforeDep) {
        FeatureVector fvHead = getFeatureVectorLabelled(conll, conll.conllSentence(), type, node, headBeforeDep, false);
        fvHead.addTo(aggregator);
    }


    public FeatureVector getFeatureVectorLabelled(ConllAdapter conll, CONLLSentence sentence, int type, int token1, boolean RA, boolean child) {
        int token = token1 - 1;
        FeatureVector fv = new FeatureVectorSparse();

        String dir = RA ? "RA" : "LA";

        dir += "&" + child;
//        System.err.println(token + "  " + sentence.size());
//        System.err.println(sentence.get(0).get(CONLLToken.FORM));
        String w = sentence.get(token).get(CONLLToken.FORM);
        String wP = sentence.get(token).get(CONLLToken.POSTAG);

        String wPm1 = token > 0 ? sentence.get(token - 1).get(CONLLToken.POSTAG) : "STR";
        String wPp1 = token < sentence.size() - 1 ? sentence.get(token + 1).get(CONLLToken.POSTAG) : "END";

        String feat = "NTS1=" + type + "&" + dir;
        fv.setWeight(featureHandler.feature(feat), 1);

        feat = "ANTS1=" + type;
        fv.setWeight(featureHandler.feature(feat), 1);

        for (int i = 0; i < 2; i++) {
            String suff = i < 1 ? "&" + dir : "";
            suff = "&" + type + suff;

            feat = "NTH=" + w + " " + wP + suff;
            fv.setWeight(featureHandler.feature(feat), 1);
            feat = "NTI=" + wP + suff;
            fv.setWeight(featureHandler.feature(feat), 1);
            feat = "NTIA=" + wPm1 + " " + wP + suff;
            fv.setWeight(featureHandler.feature(feat), 1);
            feat = "NTIB=" + wP + " " + wPp1 + suff;
            fv.setWeight(featureHandler.feature(feat), 1);
            feat = "NTIC=" + wPm1 + " " + wP + " " + wPp1 + suff;
            fv.setWeight(featureHandler.feature(feat), 1);
            feat = "NTJ=" + w + suff;
            fv.setWeight(featureHandler.feature(feat), 1);
        }

        // Martin uses sets!!!
        fv.toSet();
        return fv;
    }

    public void addOutdateListener(FeatureExtractorOutdateListener listener) {
    }

    public int[] layers() {
        return layers;
    }

    public void graphCleared(Graph graph) {
    }

    public void intFeatureChanged(Graph graph, int node, int feature, int value, int oldvalue) {
    }

    public void objectFeatureChanged(Graph graph, int node, int feature, Object value, Object oldvalue) {
    }

    public void nodeAdded(Graph graph, int node) {
    }

    public void edgeAdded(Graph graph, int layer, int innode, int outnode, int type) {
    }

    public void edgeRemoved(Graph graph, int layer, int innode, int outnode, int type) {
    }

    public void edgeMoved(Graph graph, int layer, int innode, int oldoutnode, int oldtype, int newoutnode, int newtype) {
    }

    public void edgeTypeChanged(Graph graph, int layer, int innode, int outnode, int oldtype, int newtype) {
    }

}
